package org.leveryd.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.apache.catalina.util.ParameterMap;
import org.iast.support.SimpleBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Controller
public class iastSupport {

    // curl 127.0.0.1:8085/fastjson1 -d '{"x":"y"}' -H 'Content-Type:Application/json'
    @ResponseBody
    @RequestMapping("/fastjson1")
    public String iast1(@RequestBody String params) {
        JSONObject o = JSON.parseObject(params);
        System.out.println(o.toString());

        return "iast1";
    }

    // curl 127.0.0.1:8085/fastjson2 -d '{"x":"y"}' -H 'Content-Type:Application/json'
    @ResponseBody
    @RequestMapping("/fastjson2")
    public String iast2(@RequestBody String params) {
        Object o = JSON.parse(params);
        System.out.println(o.toString());

        return "iast2";
    }

    @ResponseBody
    @RequestMapping("/file_operate")
    public String iast3(@RequestParam("filename") String filename) {
        File f = new File("/etc/"+filename);
        System.out.println(f.canRead());
        //org.springframework.boot.actuate.trace.http.HttpExchangeTracer
        //HttpTraceFilter
        return "iast3";
    }

    @ResponseBody
    @RequestMapping("/xml")
    public String iast4(@RequestBody String body) throws JsonProcessingException {
        // 如果Content-Type不设置application/json格式，post数据会被url编码. 所以访问此接口时，一定要设置content-type
        // curl -H 'Content-Type:application/json' -d '<SimpleBean><x>1</x><filename>hosts</filename></SimpleBean>'
        XmlMapper mapper = new XmlMapper();
        //SimpleBean value = mapper.readValue("<SimpleBean><x>1</x><filename>hosts</filename></SimpleBean>", SimpleBean.class);
        SimpleBean value = mapper.readValue(body, SimpleBean.class);
        System.out.println(value.getFilename());
        File f = new File("/etc/"+value.getFilename());
        System.out.println(f.canRead());
        return "iast4";
    }

    // 不能检出
    @ResponseBody
    @RequestMapping("/xss")
    public User iast5(@RequestParam("name") String name) {
        User u = new User();
        u.setName(name);
        return u;
    }

    @ResponseBody
    @RequestMapping("/iast6")
    public User iast6(@RequestParam("name") String name) {
        User u = new User();
        u.setName(name);
        Caller c = new Caller();
        c.eval(u.getName());
        return u;
    }

    @ResponseBody
    @RequestMapping("/iast7")
    public void iast7(HttpServletRequest request, HttpServletResponse response) {
        String url = request.getParameter("url");
        RequestDispatcher rd = request.getRequestDispatcher(url);

        try {
            rd.forward(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ResponseBody
    @RequestMapping("/iast8")
    public void iast8(HttpServletRequest request, HttpServletResponse response) {
        String url = request.getParameter("url");
        RequestDispatcher rd = request.getRequestDispatcher(url);
        try {
            rd.include(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 可以检出
    @ResponseBody
    @RequestMapping("/iast9")
    public String iast9(@RequestParam("name") String name) {
        User u = new User();
        u.setName(name);
        File f = new File(u.getName());
        return f.getName();
    }

    // 可以检出
    @ResponseBody
    @RequestMapping("/iast10")
    public String iast10(@RequestParam("name") String name) {
        User u = new User();
        u.setName(name);
        StringBuilder sb = new StringBuilder();
        sb = sb.append(u.getName().subSequence(0, 4));
        File f = new File(sb.toString());
        return f.getName();
    }

    // 可以检出
    @ResponseBody
    @RequestMapping("/iast11")
    public String iast11(@RequestParam("name") String name) {
        User u = new User();
        u.setName(name);
        StringBuilder sb = new StringBuilder();
        sb = sb.append(u.getName().subSequence(0, 4));  // 会有两个传播节点
        String s = sb.toString() + "xxx";   // 传播节点,似乎是内部会有StringBuilder，java.lang.StringBuilder.append
        File f = new File(s);
        return f.getName();
    }

    // 不能检出
    @ResponseBody
    @RequestMapping("/iast12")
    public String iast12(@RequestParam("name") String name) {
        List<String> l = new ArrayList<String>();
        l.add("1");
        l.add("2");
        l.add(name);
        String s = l.stream().collect(Collectors.joining(" "));
        File f = new File(s);
        return f.getName();
    }

    // 可以检出
    // curl 127.0.0.1:8085/iast13 -d '{"name":"xxx"}' -H 'Content-Type:Application/json'
    @ResponseBody
    @RequestMapping("/iast13")
    public String iast13(@RequestBody User u) {
        File f = new File(u.getName());
        return f.getName();
    }

    // 误报
    // 添加newUser为污点源后，admin字符串会被标记成污点
    @ResponseBody
    @RequestMapping("/iast14")
    public String iast14(User u) {
        newUser();
        File f = new File("admin");
        return f.getName();
    }

    public User newUser(){
        User u = new User();
        u.setName("admin");
        return u;
    }

    @ResponseBody
    @RequestMapping("/iast15")
    public String iast15(HttpServletRequest request) {
        HttpSession s = request.getSession();
        s.setMaxInactiveInterval(2000);

        HttpSession ss = request.getSession();

        File f = new File(String.valueOf(1));
        return f.getName();
    }

    @ResponseBody
    @RequestMapping("/iast16")
    public String iast16(HttpServletRequest request) {
        //request.getHeaderNames();

        // javax.servlet.http.HttpServletRequest.getSession()
        HttpSession s = request.getSession();
        s.setMaxInactiveInterval(3000);
        // org.apache.catalina.session.StandardSessionFacade x = (org.apache.catalina.session.StandardSessionFacade) s;
        // s.setAttribute("name", "admin");

        //HttpSession ss = request.getSession();
        //request.getHeader("admin");
        request.getSession();

        File f = new File(String.valueOf(1));
        return f.getName();
    }

    @ResponseBody
    @RequestMapping("/iast17")
    public String iast17(@RequestParam("name") String name) {
        ArrayList<String> a = new ArrayList<>();
        a.add("123");
        a.add(name);

        System.out.println(a);

        Iterator<String> b = a.iterator();
        System.out.println(b.next());
        System.out.println(b.next());

        File f = new File("123");
        return f.getName();
    }

    // 漏报，不能检出
    //  curl 127.0.0.1:8085/iast18 -d '[{"name":"a"},{"name":"b"}]' -H 'Content-Type:Application/json'
    @ResponseBody
    @RequestMapping("/iast18")
    public String iast18(@RequestBody List<User> users) throws IOException {
        for (User user:users){
            String username = user.getName();
            File x = new File(username);
            System.out.println(x.getName());
        }
        return "iast18";
    }

    @ResponseBody
    @RequestMapping("/iast19")
    public String iast19(@RequestBody List<User> users) throws IOException {
        for (User user:users){
            String username = user.getName();
            File x = new File(username);
            System.out.println(x.getName());
        }
        return "iast18";
    }

    // curl 127.0.0.1:8085/iast20 -d 'a=1&b=' 会导致误报
    @ResponseBody
    @RequestMapping("/iast20")
    public String iast20(HttpServletRequest request) {
        org.apache.catalina.util.ParameterMap x = (ParameterMap) request.getParameterMap();
        System.out.println(x);
        File f = new File("");
        return f.getName();
    }
}


class Sink {
    public void eval(String username){

    }
}

class Caller {
    public void eval(String username){
        Sink s = new Sink();
        s.eval(username);
    }
}
// /xss?name=%3c%69%6d%67%20%73%72%63%3d%31%20%6f%6e%65%72%72%6f%72%3d%61%6c%65%72%74%28%31%29%3e%3c%2f%69%6d%67%3e <img src=1 onerror=alert(1)>

// /iast8?url=../../../../../../../../../../../etc/hosts  没用
// /iast7?url=http://www.baidu.com  没用